package com.csii.pos.activiti.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.csii.adhoc.exception.ActStartException;
import com.csii.adhoc.exception.ActSubmitException;
import com.csii.adhoc.exception.ParamValidityException;
import com.csii.adhoc.info.user.mapper.UserMapper;
import com.csii.pos.activiti.mapper.ActivitiUofPlanMapper;
import com.csii.pos.activiti.service.ActivitiUofPlanService;
import com.csii.pos.uofplan.UofPlanPo;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * @ClassName: ActivitiUofPlanServiceImpl
 * @Author: zhanghao
 * @description: 资金计划制定工作流审批业务业务层
 * @Date: 2021/7/22 13:52
 * @Version: 1.0
 */
@Service
@Slf4j
public class ActivitiUofPlanServiceImpl implements ActivitiUofPlanService {


    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private ActivitiUofPlanMapper activitiUofPlanMapper;

    @Autowired
    private UserMapper userMapper;

    @Override
    public void deploy() {

        repositoryService.createDeployment()
                .name("资金计划审批流程部署")
                .addClasspathResource("processes/approve_uofPlan.bpmn")
                .addClasspathResource("processes/approve_uofPlan.png")
                .deploy();
    }

    @Override
    @Transactional
    public void startAndSubmit(Long id) {
        if(StringUtils.isEmpty(id))
            throw new ParamValidityException("资金计划主键id为空!");
        //获取登录用户名(此用户名是唯一的)
        String userName = (String) SecurityUtils.getSubject().getPrincipal();
        if (null == userName || "".equals(userName)) {
            throw new RuntimeException("没有获取到当前登录的用户名！");
        }
        //查询中文用户名
        String chUserName = userMapper.selectUserByUserName(userName).getName();
        //获取主键,并拼接为BusinessKey(实体对象名_主键id)
        String BusinessKey = "UofPlanPo_" + id;
        //根据主键查询审批状态
        String status = activitiUofPlanMapper.getApproveStage(id);
        //是驳回状态只提交
        if ("4".equals(status)){
            //*******************提交审批流程************************************
            //根据流程key、businessKey、当前用户名查询task
            String taskId = taskService.createTaskQuery().processDefinitionKey("approve_uofPlan").
                    processInstanceBusinessKey(BusinessKey).taskAssignee(userName).singleResult().getId();
            //提交申请
            taskService.complete(taskId);
            //更新当前数据状态为审批中
            HashMap<String, Object> map = new HashMap<>();
            map.put("id", id);
            map.put("status", "1");
            map.put("submitter",chUserName);
            activitiUofPlanMapper.updateStatusById(map);
            //驳回后提交,要清空之前审批员的审批意见.
            activitiUofPlanMapper.clearInfo(id);

        } else {
            //不是驳回状态,则启动流程并提交
            //*******************1.启动流程实例************************************
            //根据businessKey查询是否已启动实例,防止重复提交
            ProcessInstance planInstance = runtimeService.createProcessInstanceQuery().processDefinitionKey("approve_uofPlan").processInstanceBusinessKey(BusinessKey).singleResult();
            if( null != planInstance)
                throw new ActSubmitException("请勿重复提交!");

            //设置当前登录的用户为第一个节点的负责人
            HashMap<String, Object> varibles = new HashMap<>();
            varibles.put("user", userName);
            //启动流程
            try {
                runtimeService.startProcessInstanceByKey("approve_uofPlan", BusinessKey, varibles);
            }catch (ActStartException e){
                log.error("资金计划启动审批流程失败!");
                throw new ActStartException("新增资金计划时启动审批流程异常！请删除后重新添加。");
            }
            //*******************2.提交审批流程************************************
            //根据流程key、businessKey、当前用户名查询task
            String taskId = taskService.createTaskQuery().processDefinitionKey("approve_uofPlan").
                    processInstanceBusinessKey(BusinessKey).taskAssignee(userName).singleResult().getId();
            //提交申请
            taskService.complete(taskId);
            //更新当前数据状态为审批中
            HashMap<String, Object> map = new HashMap<>();
            map.put("id", id);
            map.put("status", "1");
            map.put("submitter",chUserName);
            activitiUofPlanMapper.updateStatusById(map);
        }



    }

    @Override
    public void start(UofPlanPo uofPlanPo) {
        if (StringUtils.isEmpty(uofPlanPo.getUofItemSn())){
            throw new ParamValidityException("uofPlanPo主键为空!");
        }
        //1.获取主键,并拼接为BusinessKey(实体对象名_主键id)
        String BusinessKey = "UofPlanPo_" + uofPlanPo.getUofItemSn().toString();
        //2.设置当前登录的用户为第一个节点的负责人
        HashMap<String, Object> varibles = new HashMap<>();
        String userName = (String) SecurityUtils.getSubject().getPrincipal();
        varibles.put("user", userName);
        //3.启动流程
        try {
            runtimeService.startProcessInstanceByKey("approve", BusinessKey, varibles);
        }catch (ActStartException e){
            throw new ActStartException("新增资金计划时启动审批流程异常！请删除后重新添加。");
        }
    }

    @Override
    @Transactional
    public void submit(List<String> idList) {
        String userName = (String) SecurityUtils.getSubject().getPrincipal();
        if(idList.size() == 0)
            throw new ParamValidityException("至少选中一条数据！");
        //处理批量提交
        for (String id : idList){
            if (StringUtils.isEmpty(id)){
                log.error("当前选中的数据 {} 中,其中有主键为空的值!", idList.toString());
                //throw new ParamValidityException("选中的某条数据主键为空!");
            }
            //拼接businessKey(实体对象名_主键id)
            String businessKey = "UofPlanPo_" + id;
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processDefinitionKey("approve_uofPlan").processInstanceBusinessKey(businessKey).singleResult();
            if (processInstance == null){
                throw new ActSubmitException("当前资金计划未启动审批流程，请删除后重新新增资金计划！");
            }
            Task task = taskService.createTaskQuery()
                    .processInstanceId(processInstance.getId())
                    .taskAssignee(userName)
                    .singleResult();
            //判断是否任务已提交
            if (task == null)
                throw new ActSubmitException("此资金计划已提交，请核查数据审批状态！");
            //提交申请
            taskService.complete(task.getId());
            //更新当前数据状态为审批中
            HashMap<String, Object> map = new HashMap<>();
            map.put("id", id);
            map.put("status", "1");
            activitiUofPlanMapper.updateStatusById(map);

        }
    }

    /**
     * 删除流程实例
     * @param
     */
    @Override
    public void delete(Long id) {
//        for (String id : idList){
            if (null == id ){
                throw new ParamValidityException("主键有误!");
            }
            //拼接businessKey(实体对象名_主键id)
            String businessKey = "UofPlanPo_" + id;
            ProcessInstance instanceSigle =
                    runtimeService.createProcessInstanceQuery().processDefinitionKey("approve_uofPlan").processInstanceBusinessKey(businessKey).singleResult();
            if (instanceSigle == null)
                return;
            runtimeService.deleteProcessInstance(instanceSigle.getId(), "提交人删除申请资金计划！");
//        }
    }

    @Override
    public IPage<UofPlanPo> findAllInfo(Page<UofPlanPo> page, UofPlanPo uofPlanPo) {
        if (StringUtils.isEmpty(uofPlanPo.getApproveStage())){
            throw new ParamValidityException("审批阶段approveStage不能为空!");
        }
        if ("1".equals(uofPlanPo.getApproveStage()) && (StringUtils.isEmpty(uofPlanPo.getUofPlanItlNo())) ){
            throw new ParamValidityException("部门领导审批阶段部门编号uofPlanItlNo不能为空!");
        }
        String assignee = null;
        //1-部门领导  2-分管领导  3-总经理
        if ("1".equals(uofPlanPo.getApproveStage())){
            assignee = "部门领导";
        } else if ("2".equals(uofPlanPo.getApproveStage())){
            assignee = "分管领导";
        } else if ("3".equals(uofPlanPo.getApproveStage())){
            assignee = "总经理";
        }
        List<Task> taskList = taskService.createTaskQuery().processDefinitionKey("approve_uofPlan").taskAssignee(assignee).list();
        List<String> ids = new ArrayList<>();
        //若无任务,则返回空
        if (taskList.size() == 0) {
            Page<UofPlanPo> uof = new Page<>();
            return uof;
        }
        for (Task task : taskList) {
            String processInstanceId = task.getProcessInstanceId();
            String businessKey = runtimeService.createProcessInstanceQuery().processDefinitionKey("approve_uofPlan")
                    .processInstanceId(processInstanceId).singleResult().getBusinessKey();
            //businessKey的格式为uofPlan_id , 遍历截取id
            ids.add(businessKey.split("_")[1]);
        }
        IPage<UofPlanPo> list = activitiUofPlanMapper.findAllInfo(page, ids, uofPlanPo);
        return list;
    }



    @Override
    public  void agreeByApprover(UofPlanPo uofPlanPo) {

        //必传阶段编号和主键UofItemSn
        if (StringUtils.isEmpty(uofPlanPo.getApproveStage()) || StringUtils.isEmpty(uofPlanPo.getUofItemSn())) {
            log.error("阶段编号或主键id为空!");
            throw new ParamValidityException("阶段编号或主键id为空!");
        }

        //通过当前记录组装 businessKey,并通过 businessKey获取当前正在运行的task.
        String businessKey = "UofPlanPo_" + uofPlanPo.getUofItemSn();
        Task task = taskService.createTaskQuery().processDefinitionKey("approve_uofPlan").processInstanceBusinessKey(businessKey).singleResult();
        //当前登录用户
        String userName = (String) SecurityUtils.getSubject().getPrincipal();
        if (null == userName || "".equals(userName)) {
            throw new RuntimeException("没有获取到当前登录的用户名！");
        }
        //查询中文用户名
        String chUserName = userMapper.selectUserByUserName(userName).getName();
        HashMap<String, Object> map = new HashMap<>();
        map.put("status","2");
        //通过Assignee名称分别处理不同领导审批
        //approveStage 1-部门领导  2-分管领导  3-总经理
        if ("1".equals(uofPlanPo.getApproveStage()) && "部门领导".equals(task.getAssignee())) {
            //complete当前此任务
            taskService.complete(task.getId(), map);
            //更新业务表
            map.put("id", uofPlanPo.getUofItemSn());
            map.put("desc", uofPlanPo.getBusnLeaderDesc());
            map.put("approver", chUserName);
            activitiUofPlanMapper.updateLeaderDescById(map);
        } else if ("2".equals(uofPlanPo.getApproveStage()) && "分管领导".equals(task.getAssignee())){
            //complete当前此任务
            taskService.complete(task.getId(), map);
            //更新业务表
            map.put("id", uofPlanPo.getUofItemSn());
            map.put("desc", uofPlanPo.getBusnFinanceDesc());
            map.put("approver", chUserName);
            activitiUofPlanMapper.updateFinanceDescById(map);

        } else if ("3".equals(uofPlanPo.getApproveStage()) && "总经理".equals(task.getAssignee())) {
            //complete当前此任务
            taskService.complete(task.getId(), map);
            //更新业务表
            map.put("id", uofPlanPo.getUofItemSn());
            map.put("desc", uofPlanPo.getBossDesc());
            activitiUofPlanMapper.updateBossDescById(map);
            //如果流程结束,则更新数据状态为同意
            if (null == runtimeService.createProcessInstanceQuery().processInstanceBusinessKey(businessKey).singleResult()){
                activitiUofPlanMapper.updateStatusById(map);
            }
        } else {
            log.error("当前资金计划 id= {} 提交的审批数据审批状态异常,请关注!", uofPlanPo.getUofItemSn().toString());
            throw new ActSubmitException("审批同意操作失败!");
        }

    }


    @Override
    public void rejectByApprover(UofPlanPo uofPlanPo) {

        //必传阶段编号和主键UofItemSn
        if (StringUtils.isEmpty(uofPlanPo.getApproveStage()) || StringUtils.isEmpty(uofPlanPo.getUofItemSn())) {
            log.error("阶段编号或主键id为空!");
            throw new ParamValidityException("阶段编号或主键id为空!");
        }
        //通过当前记录组装 businessKey,并通过 businessKey获取当前正在运行的 task.
        String businessKey = "UofPlanPo_" + uofPlanPo.getUofItemSn();
        Task task = taskService.createTaskQuery().processDefinitionKey("approve_uofPlan").processInstanceBusinessKey(businessKey).singleResult();
        //当前登录用户
        String userName = (String) SecurityUtils.getSubject().getPrincipal();
        if (null == userName || "".equals(userName)) {
            throw new RuntimeException("没有获取到当前登录的用户名！");
        }
        //查询中文用户名
        String chUserName = userMapper.selectUserByUserName(userName).getName();
        HashMap<String, Object> map = new HashMap<>();
        map.put("status","3");
        //通过Assignee名称分别处理不同领导审批
        //approveStage 1-部门领导  2-分管领导  3-总经理
        if ("1".equals(uofPlanPo.getApproveStage()) && "部门领导".equals(task.getAssignee())) {
            //complete当前此任务
            taskService.complete(task.getId(), map);
            //更新业务表
            map.put("id", uofPlanPo.getUofItemSn());
            map.put("desc", uofPlanPo.getBusnLeaderDesc());
            map.put("approver", chUserName);
            activitiUofPlanMapper.updateLeaderDescById(map);
        } else if ("2".equals(uofPlanPo.getApproveStage()) && "分管领导".equals(task.getAssignee())){
            //complete当前此任务
            taskService.complete(task.getId(), map);
            //更新业务表
            map.put("desc", uofPlanPo.getBusnFinanceDesc());
            map.put("id", uofPlanPo.getUofItemSn());
            map.put("approver", chUserName);
            activitiUofPlanMapper.updateFinanceDescById(map);

        } else if ("3".equals(uofPlanPo.getApproveStage()) && "总经理".equals(task.getAssignee())) {
            //complete当前此任务
            taskService.complete(task.getId(), map);
            //更新业务表
            map.put("desc", uofPlanPo.getBossDesc());
            map.put("id", uofPlanPo.getUofItemSn());
            activitiUofPlanMapper.updateBossDescById(map);

        } else {
            log.error("当前资金计划 id= {} 提交的审批数据审批状态异常,请关注!", uofPlanPo.getUofItemSn().toString());
            throw new ActSubmitException("审批拒绝操作失败!");
        }

        //如果流程结束,则更新数据状态为拒绝
        if (null == runtimeService.createProcessInstanceQuery().processInstanceBusinessKey(businessKey).singleResult()){
            activitiUofPlanMapper.updateStatusById(map);
        }


    }

    @Override
    public void refuteByApprover(UofPlanPo uofPlanPo) {
        //必传阶段编号和主键UofItemSn
        if (StringUtils.isEmpty(uofPlanPo.getApproveStage()) || StringUtils.isEmpty(uofPlanPo.getUofItemSn())) {
            log.error("阶段编号或主键id为空!");
            throw new ParamValidityException("阶段编号或主键id为空!");
        }
        //通过当前记录组装 businessKey,并通过 businessKey获取当前正在运行的 task.
        String businessKey = "UofPlanPo_" + uofPlanPo.getUofItemSn();
        Task task = taskService.createTaskQuery().processDefinitionKey("approve_uofPlan").processInstanceBusinessKey(businessKey).singleResult();
        //当前登录用户
        String userName = (String) SecurityUtils.getSubject().getPrincipal();
        if (null == userName || "".equals(userName)) {
            throw new RuntimeException("没有获取到当前登录的用户名！");
        }
        //查询中文用户名
        String chUserName = userMapper.selectUserByUserName(userName).getName();
        HashMap<String, Object> map = new HashMap<>();
        map.put("status","4");
        //通过Assignee名称分别处理不同领导审批
        //approveStage 1-部门领导  2-分管领导  3-总经理
        if ("1".equals(uofPlanPo.getApproveStage()) && "部门领导".equals(task.getAssignee())) {
            //complete当前此任务
            taskService.complete(task.getId(), map);
            //更新业务表
            map.put("id", uofPlanPo.getUofItemSn());
            map.put("desc", uofPlanPo.getBusnLeaderDesc());
            map.put("approver", chUserName);
            activitiUofPlanMapper.updateLeaderDescById(map);
        } else if ("2".equals(uofPlanPo.getApproveStage()) && "分管领导".equals(task.getAssignee())){
            //complete当前此任务
            taskService.complete(task.getId(), map);
            //更新业务表
            map.put("desc", uofPlanPo.getBusnFinanceDesc());
            map.put("id", uofPlanPo.getUofItemSn());
            map.put("approver", chUserName);
            activitiUofPlanMapper.updateFinanceDescById(map);

        } else if ("3".equals(uofPlanPo.getApproveStage()) && "总经理".equals(task.getAssignee())) {
            //complete当前此任务
            taskService.complete(task.getId(), map);
            //更新业务表
            map.put("desc", uofPlanPo.getBossDesc());
            map.put("id", uofPlanPo.getUofItemSn());
            activitiUofPlanMapper.updateBossDescById(map);

        } else {
            log.error("当前资金计划 id= {} 提交的审批数据审批状态异常,请关注!", uofPlanPo.getUofItemSn().toString());
            throw new ActSubmitException("审批驳回操作失败!");
        }
        //更新业务数据为驳回状态
        activitiUofPlanMapper.updateStatusById(map);
    }
}
